﻿
using System;
using System.Xml.Linq;
namespace CharacterCreation.Business
{
    public class ObjectMapper
    {
        public static TResult Parse<TSource, TResult>(TSource s) where TResult : new()
        {

            if (s == null) throw new Exception("source is null");

            TResult r = new TResult();

            foreach (var pInfo in typeof(TSource).GetProperties())
            {

                var targetProperty = typeof(TResult).GetProperty(pInfo.Name);
                if (targetProperty == null) continue;

                if (targetProperty.PropertyType.IsEnum &&
                    pInfo.PropertyType.ToString() == "System.String")
                {
                    targetProperty.SetValue(
                        r,
                        Enum.Parse(targetProperty.PropertyType, pInfo.GetValue(s, null).ToString(), true),
                        null);
                }
                else if (pInfo.PropertyType.IsEnum &&
                    targetProperty.PropertyType.ToString() == "System.String")
                {
                    targetProperty.SetValue(r, pInfo.GetValue(s, null).ToString(), null);
                }
                else
                {
                    object result = pInfo.GetValue(s, null);
                    targetProperty.SetValue(r, result, null);
                }
            }

            return r;

        }

        public static TResult Parse<TResult>(XElement source) where TResult : new()
        {
            TResult r = new TResult();

            foreach (var pInfo in typeof(TResult).GetProperties())
            {
                //Parse enum
                if (pInfo.PropertyType.IsEnum && source.Element(pInfo.Name) != null)
                {
                    dynamic value = Enum.Parse(pInfo.PropertyType, source.Element(pInfo.Name).Value.ToString());
                    pInfo.SetValue(r, value, null);
                    continue;
                }

                //Parse for default properties
                if (source.Element(pInfo.Name) != null)
                {
                    dynamic value = null;
                    switch (pInfo.PropertyType.ToString())
                    {
                        case "System.String":
                            value = source.Element(pInfo.Name).Value.ToString();
                            break;
                        case "System.Int16":
                        case "System.Int32":
                        case "System.Int64":
                            value = int.Parse(source.Element(pInfo.Name).Value.ToString());
                            break;
                        case "System.Boolean":
                            value = int.Parse(source.Element(pInfo.Name).Value.ToString());
                            break;
                        case "System.DateTime":
                            value = DateTime.Parse(source.Element(pInfo.Name).Value.ToString());
                            break;
                        case "System.Double":
                            value = double.Parse(source.Element(pInfo.Name).Value.ToString());
                            break;
                        case "System.Guid":
                            value = Guid.Parse(source.Element(pInfo.Name).Value.ToString());
                            break;
                        default:
                            value = source.Element(pInfo.Name).Value.ToString();
                            break;
                    }
                    pInfo.SetValue(r, value, null);
                }
            }

            return r;
        }
    }
}
